home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Amster - Upload
- ** by Jacob Laursen <laursen@myself.com>
- */
-
- #include "include/config.h"
-
- #include <stdio.h>
- #include <stdlib.h>
-
- #include <proto/dos.h>
- #include <proto/exec.h>
- #include <proto/socket.h>
-
- #include <netdb.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <netinet/tcp.h>
- #include <bsdsocket/socketbasetags.h>
- #include <error.h>
- #include <time.h>
-
- #include "include/mui.h"
- #include <MUI/NListview_mcc.h>
- #include "include/gui.h"
- #include "include/panel.h"
- #include "include/prefs.h"
- #include "include/share.h"
- #include "include/transfer.h"
- #include "include/upload.h"
- #include "amster_Cat.h"
- #include "include/protos.h"
-
-
- #define ULC_STATE 0
- #define ULC_SIZE 1
-
- int ul_count = 0;
-
- ULONG ul_new(struct IClass *cl, Object *obj, struct opSet *msg);
- void ul_cps(struct TransferData *data);
-
-
- MUIF ul_dispatch(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
- {
- struct TransferData *data;
-
- switch(msg->MethodID) {
- case OM_NEW:
- return(ul_new(cl, obj, (APTR)msg));
- case MUIM_Window_Setup:
- return(dl_setup(cl, obj, (APTR)msg));
- case MUIM_Window_Cleanup:
- return(dl_muicleanup(cl, obj, (APTR)msg));
- case UPLOAD_OPEN:
- set(obj, MUIA_Window_Open, TRUE);
- return NULL;
- case UPLOAD_CLOSE:
- set(obj, MUIA_Window_Open, FALSE);
- return NULL;
- case UPLOAD_UPDATE:
- {
- long pos = MUIV_NList_GetPos_Start;
- data = INST_DATA(cl, obj);
- DoMethod(data->list, MUIM_NList_GetPos, (((muimsg)msg)->arg1), &pos);
- DoMethod(data->list, MUIM_NList_Redraw, pos);
- return NULL;
- }
- case UPLOAD_CPS:
- data = INST_DATA(cl, obj);
- ul_cps(data);
- return NULL;
- case UPLOAD_ADD:
- data = INST_DATA(cl, obj);
- DoMethod(data->list, MUIM_NList_InsertSingle, (songtrans)(((muimsg)msg)->arg1), MUIV_NList_Insert_Bottom);
- return NULL;
- case UPLOAD_START:
- data = INST_DATA(cl, obj);
- ul_startq2(data, (char *)(((muimsg)msg)->arg1), (char *)(((muimsg)msg)->arg2), (u_long)(((muimsg)msg)->arg3), (int)(((muimsg)msg)->arg4));
- return NULL;
- case UPLOAD_INFO:
- data = INST_DATA(cl, obj);
- TransferInfo(data);
- return NULL;
- case UPLOAD_ABORT:
- data = INST_DATA(cl, obj);
- TransferAbort(data);
- return NULL;
- case UPLOAD_CLEANUP:
- data = INST_DATA(cl, obj);
- TransferCleanup(data);
- return NULL;
- case UPLOAD_CLEANUP_SINGLE:
- {
- long pos;
- songtrans sd = (songtrans)(((muimsg)msg)->arg1);
- data = INST_DATA(cl, obj);
-
- pos = MUIV_NList_GetPos_Start;
- DoMethod(data->list, MUIM_NList_GetPos, sd, &pos);
- DoMethod(data->list, MUIM_NList_Remove, pos);
-
- return NULL;
- }
- case UPLOAD_WATCHER:
- data = INST_DATA(cl, obj);
- TransferWatcher(data);
- return NULL;
- case UPLOAD_COUNTDECREMENT:
- data = INST_DATA(cl, obj);
- if (--ul_count == 0) DoMethod(_app(obj), MUIM_Application_RemInputHandler, &data->watchnode);
- return NULL;
- case UPLOAD_COUNTINCREMENT:
- data = INST_DATA(cl, obj);
- if (ul_count++ == 0) DoMethod(_app(obj), MUIM_Application_AddInputHandler, &data->watchnode);
- return NULL;
- }
- return DoSuperMethodA(cl, obj, msg);
- }
-
-
- ULONG ul_new(struct IClass *cl, Object *obj, struct opSet *msg)
- {
- static struct Hook uplistdispHook = { {0,0}, &translistdisp, NULL, NULL };
- static struct Hook uplistdestHook = { {0,0}, &translistdest, NULL, NULL };
- struct TransferData *data;
- Object *list, *info, *BT_Abort, *BT_Clean;
-
- if (obj = (Object *)DoSuperNew(cl,obj,
- MUIA_Window_Title, MSG_UPLOAD_TITLE,
- MUIA_Window_ID, MAKE_ID('U','P','L','D'),
- WindowContents, VGroup,
- Child, list = NListviewObject,
- MUIA_NListview_NList, NListObject,
- InputListFrame,
- MUIA_Font, MUIV_Font_Tiny,
- MUIA_NList_Title, TRUE,
- MUIA_NList_Format, "BAR, BAR, BAR, BAR, BAR",
- MUIA_NList_DisplayHook, &uplistdispHook,
- MUIA_NList_DestructHook, &uplistdestHook,
- MUIA_CycleChain, 1,
- End,
- End,
- Child, info = TextObject,
- TextFrame,
- MUIA_Background, MUII_TextBack,
- MUIA_Text_PreParse, "\33c",
- End,
- Child, HGroup,
- Child, BT_Abort = SimpleButton(MSG_UPLOAD_ABORT_GAD),
- Child, BT_Clean = SimpleButton(MSG_UPLOAD_CLEANUP_GAD),
- End,
- End,
- TAG_MORE, msg->ops_AttrList))
- {
- data = INST_DATA(cl,obj);
- data->list = list;
- data->info = info;
-
- data->ihnode.ihn_Object = obj;
- data->ihnode.ihn_Millis = 1000;
- data->ihnode.ihn_Method = UPLOAD_CPS;
- data->ihnode.ihn_Flags = MUIIHNF_TIMER;
-
- data->watchnode.ihn_Object = obj;
- data->watchnode.ihn_Millis = 10000;
- data->watchnode.ihn_Method = UPLOAD_WATCHER;
- data->watchnode.ihn_Flags = MUIIHNF_TIMER;
-
- DoMethod(BT_Abort, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, UPLOAD_ABORT );
- DoMethod(BT_Clean, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, UPLOAD_CLEANUP);
- DoMethod(list, MUIM_Notify, MUIA_NList_EntryClick, MUIV_EveryTime, obj, 1, UPLOAD_INFO);
- DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, obj, 1, UPLOAD_CLOSE);
-
- return((ULONG)obj);
- }
- return(0);
- }
-
-
- void ul_cps(struct TransferData *data)
- {
- songtrans sd;
- u_long item;
- int i;
-
- for (i=0; ; i++) {
- DoMethod(data->list, MUIM_NList_GetEntry, i, &item);
- if (!item) return;
- sd = (songtrans)item;
- if (sd->state == DLS_UP) {
- CalculateCps(sd);
- DoMethod(gui->uwin, UPLOAD_UPDATE, sd);
- }
- }
- }
-
-
- void ul_addq(song s)
- /* This is the initial function, called from share.c */
- {
- songtrans sd;
- char *path;
-
- path = MakeWinPath(s->title);
- if (ul_count < prf->UploadQueueLimit) {
- sprintf(nap_buf, "%s \"%s\"", s->user, path);
- free(path);
- nap_send(NAPC_UPLOADACCEPT);
- }
- else {
- sprintf(nap_buf, "%s \"%s\" %d", s->user, path, prf->UploadQueueLimit);
- free(path);
- nap_send(NAPC_LOCALQUEUEFULL);
- return;
- }
-
- sd = malloc(sizeof(_songtrans));
- if (!sd) return;
- memset(sd, 0, sizeof(_songtrans));
-
- sd->song = nap_songdup(s);
- if (!sd->song) {
- free(sd);
- return;
- }
-
- sd->size = s->size;
- sd->mynick = prf->user;
- sd->type = TYPE_UPLOAD_OUT;
- sd->reqtime = time(NULL);
-
- DoMethod(gui->uwin, UPLOAD_COUNTINCREMENT);
-
- DoMethod(gui->uwin, UPLOAD_ADD, sd);
- }
-
-
- void ul_startq(char *title, char *user, u_long ip, int port, int link)
- /* This is the initial function, when the actual upload is about to
- take place (acknowledged by server) - called from napster.c */
- {
- DoMethod(gui->uwin, UPLOAD_START, title, user, ip, port);
- }
-
-
- void ul_startq2(struct TransferData *data, char *title, char *user, u_long ip, int port)
- /* ul_startq() continued (to get TransferData struct) */
- {
- u_long tmp;
- songtrans sd;
- long i;
- char *path;
-
- for (i=0; ; i++) {
- DoMethod(data->list, MUIM_NList_GetEntry, i, &tmp);
- if (!tmp) return;
- sd = (songtrans)tmp;
- path = MakeWinPath(sd->song->title);
- if (sd->state==DLS_PREP && stricmp(user, sd->song->user)==0 && strcmp(title, path)==0) break;
- }
- free(path);
-
- if (sd->t) return; /* Already in a thread */
-
- /* We haven't filled out sd->song completely yet, since not much
- information was available when the request was made */
- sd->song->ip = ip;
-
- /* Why do we need the IP twice? Check and use only one of them! */
- sd->ip = ip;
- sd->port = port;
-
- sd->t = th_spawn(ul_handlemsg, "Amster uploader", UploadThread, prf->UploadTaskPri, sd);
- if (!sd->t) {
- sd->state = DLS_ERROR;
- DoMethod(gui->uwin, DL_UPDATE, sd);
- }
- }
-
-
- void ul_handlemsg(thread t, int com, APTR data)
- {
- songtrans sd=(songtrans)t->data;
-
- switch(com) {
- case THC_STARTUP:
- sd->ts = 1;
- nap_sendbuf(NAPC_ULINC, "");
- break;
- case THC_EXIT:
- sd->error = (int)data;
- if (sd->error == 0) DoMethod(gui->shwin, SHARE_UPDCOUNT, sd->song->title);
- TransferHandleError(sd);
- sd->ts = 0;
- sd->t = NULL;
- DoMethod(gui->uwin, UPLOAD_COUNTDECREMENT);
- nap_sendbuf(NAPC_ULCOMPLETE, "");
- if (sd->state == DLS_FIN && prf->AutoCleanup) {
- DoMethod(gui->uwin, UPLOAD_CLEANUP_SINGLE, sd);
- break;
- }
- break;
- case DLC_STATE:
- sd->state = (int)data;
- case DLC_UPDATE:
- DoMethod(gui->uwin, UPLOAD_UPDATE, sd);
- break;
- }
- }
-
-
- /* Upload thread */
-
- __asm __saveds void UploadThread(void)
- {
- thread t;
- songtrans sd;
- struct Library *DosBase;
- struct Library *SocketBase;
- char *buffer, *path;
- long tmp;
- long s;
- thmsg m;
- int len;
-
- t = thr_init();
- if (!t) return;
- sd = t->data;
-
- if (!InitTransferThread(t, sd)) return;
- s = sd->s;
- buffer = sd->buffer;
- DosBase = sd->DosBase;
- SocketBase = sd->SocketBase;
-
- while (1) {
- u_long sigs;
-
- sigs = Wait(sd->nsigm|sd->msigm);
- if (sigs&(sd->msigm)) {
- m = (thmsg)GetMsg(t->port);
- if(m) {
- if (m->com == THC_EXIT) {
- thr_message(t, DLC_STATE, (APTR)DLS_ABORT);
- ExitTransferThread(sd, 0);
- return;
- }
- if (!m->isreply) {
- m->isreply=1;
- ReplyMsg((struct Message *)m);
- }
- }
- }
-
- if (sigs&(sd->nsigm)) {
- FD_ZERO(&sd->fds);
- FD_SET(s,&sd->fds);
- sd->tv.tv_sec = 0;
- sd->tv.tv_usec = 0;
-
- switch(sd->state) {
- case DLS_CON:
- if (WaitSelect(s+1,NULL,&sd->fds,NULL,&sd->tv,0) != 1) break;
- {
- sd->state = DLS_INIT;
- tmp = 0;
- IoctlSocket(s, FIONBIO, (char*)&tmp);
- /* Disable non-blocking I/O to the socket */
- }
-
- case DLS_INIT:
- if (WaitSelect(s+1,&sd->fds,NULL,NULL,&sd->tv,0) != 1) break;
- {
- tmp = recv(s, buffer, 1, 0);
- if (tmp != 1) {
- sd->ErrorCode = Errno();
- ExitTransferThread(sd, ERROR_NET);
- return;
- }
- if (buffer[0] != '1') {
- ExitTransferThread(sd, 30);
- return;
- }
- thr_message(t, DLC_UPDATE, 0);
- send(s, "SEND", 4, 0);
-
- path = MakeWinPath(sd->song->title);
- sprintf(buffer, "%s \"%s\" %ld", sd->mynick, path, sd->song->size);
- free(path);
- send(s, buffer, strlen(buffer),0);
-
- tmp = recv(s, buffer, 32, 0);
- if (tmp < 1) {
- sd->ErrorCode = Errno();
- ExitTransferThread(sd, ERROR_NET);
- return;
- }
- buffer[tmp] = '\0';
-
- sd->cur = atoi(buffer);
- if (sd->cur == 0 && buffer[0] != '0') {
- if (strcmp(buffer, "FILE NOT REQUESTED") == 0) {
- ExitTransferThread(sd, ERROR_NOTREQUESTED);
- return;
- }
- ExitTransferThread(sd, 31);
- return;
- }
-
- sd->f = Open(sd->song->title, MODE_OLDFILE);
- if (!sd->f) {
- sd->ErrorCode = IoErr();
- ExitTransferThread(sd, ERROR_FILEOPEN);
- return;
- }
-
- Seek(sd->f, sd->cur, OFFSET_BEGINNING);
- sd->state = DLS_UP;
- sd->starttime = time(NULL);
- sd->resumestart = sd->cur;
- thr_message(t, DLC_UPDATE, 0);
- }
-
- case DLS_UP:
- if (WaitSelect(s+1,NULL,&sd->fds,NULL,&sd->tv,0) != 1) break;
- while (sd->cur < sd->size) {
-
- len = Read(sd->f, buffer, 4096);
- if (len == -1) { /* Error */
- sd->ErrorCode = IoErr();
- ExitTransferThread(sd, ERROR_FILEREAD);
- return;
- }
- if (len != 0) {
- tmp = send(s, buffer, len, 0);
- if (tmp == -1) {
- sd->ErrorCode = Errno();
- ExitTransferThread(sd, ERROR_NET);
- return;
- }
- sd->cur += len;
- }
-
- if (len < 4096 && sd->cur < sd->size) {
- /* Read buffer wasn't filled and file is not finished */
- thr_message(t, DLC_STATE, (APTR)DLS_ERROR);
- ExitTransferThread(sd, 33);
- return;
- }
-
- m = (thmsg)GetMsg(t->port);
- if (m) {
- if (m->com == THC_EXIT) {
- thr_message(t, DLC_STATE, (APTR)DLS_ABORT);
- ExitTransferThread(sd, 0);
- return;
- }
- if (!m->isreply) {
- m->isreply=1;
- ReplyMsg((struct Message *)m);
- }
- }
-
- FD_ZERO(&sd->fds);
- FD_SET(s,&sd->fds);
- }
-
- thr_message(t, DLC_STATE, (APTR)DLS_FIN);
- ExitTransferThread(sd, 0);
- return;
-
- }
- }
- }
-
- ExitTransferThread(sd, 0);
- }
-